// handles going back to real mode to call an interrupt

/** process:
1) Load the segment registers with real-mode compatible values.. 
2) Reset the Protection Enable (PE) bit in CR0.. 
3) Load the segment registers with real mode values.. 
4) Inhibit A20 from the address bus (gate A20 off).. 
**/

#include <system.h>

// empties the 8042 buffer
void Empty8042()
{
	while( true )
	{
		uchar_t tmp = inportb( 0x64 );
		if( ( tmp & 2 ) == 0 )
			return;
	}
}

// disables the A20 line
void DisableA20()
{
	// disable interrupts
	asm( "cli" );
	
	// load in real-mode registers
	__asm__ __volatile__ (	"jmpl $0x18,$load_rm\n\t"
							"load_rm:\n\t"
							"movw $0x20,%ax\nmovw %ax,%ds\nmovw %ax,%es\nmovw %ax,%fs\nmovw %ax,%gs\n"
							);
	
	// unset the appropriate bit in CR0
	write_cr0( read_cr0() & 0xFFFFFFF0 );
	
	// load in real-mode registers (again)
//	__asm__ __volatile__ ( "movw $0x18,%ax\nmovw %ax,%cs\nmovw $0x20,%ax\nmovw %ax,%ds\nmovw %ax,%es\nmovw %ax,%fs\nmovw %ax,%gs\n" );
	
	// empty the buffer
	Empty8042();
	
	// disable the keyboard
/*	outportb( 0x64, 0xD1 );
	
	// empty the buffer
	Empty8042();*/
	
	// turn off the A20 line
	outportb( 0x60, 0xDD );
	
	// empty the buffer
//	Empty8042();
	
	// enable interrupts
	asm( "sti" );
}

// disables the A20 line
void EnableA20()
{
	// empty the buffer
	Empty8042();
	
	// disable the keyboard
/*	outportb( 0x64, 0xD1 );
	
	// empty the buffer
	Empty8042();*/
	
	// turn on the A20 line
	outportb( 0x60, 0xDF );
	
	// empty the buffer
//	Empty8042();
	
	// load in protected-mode registers
	__asm__ __volatile__ ( "movw $0x08,%ax\nmovw %ax,%cs\nmovw $0x10,%ax\nmovw %ax,%ds\nmovw %ax,%es\nmovw %ax,%fs\nmovw %ax,%gs\n" );
	
	// set the appropriate bit in CR0
	write_cr0( read_cr0() | 0x1 );
	
	// load in protected-mode registers (again)
	__asm__ __volatile__ ( "movw $0x08,%ax\nmovw %ax,%cs\nmovw $0x10,%ax\nmovw %ax,%ds\nmovw %ax,%es\nmovw %ax,%fs\nmovw %ax,%gs\n" );
}

extern "C" void enter_rm();

// calls a real-mode interrupt
void int_v86( int intnum )
{
	/// --kmcguire: Getting rid of symbol dependancies during linking. You said these were not used anymore?
	// disable the A20 line
	//DisableA20();
	//enter_rm();
	//while( 1 );
	
	// don't worry about registers...
/*	__asm__ __volatile__ ( "int $0x3" );
	
	// enable the A20 line
	EnableA20();*/
}
